﻿#if NEW_INPUT_SYSTEM
using Devil;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.InputSystem.LowLevel;

namespace GameToolkit
{
    public class NewInputXboxController : InputController
    {
        Gamepad mGamepad;
        List<KeyInfo> mKeys;
        public override EControllerType ControllerType => EControllerType.Controller;

        public override void Prepare(GameInput ginput)
        {
            base.Prepare(ginput);
            mKeys = new List<KeyInfo>();
            mKeys.Add(new KeyInfo(EControllerType.Controller, false, ECustomizableKey.Customizable, "A", (int)GamepadButton.South));
            mKeys.Add(new KeyInfo(EControllerType.Controller, false, ECustomizableKey.Customizable, "B", (int)GamepadButton.East));
            mKeys.Add(new KeyInfo(EControllerType.Controller, false, ECustomizableKey.Customizable, "X", (int)GamepadButton.West));
            mKeys.Add(new KeyInfo(EControllerType.Controller, false, ECustomizableKey.Customizable, "Y", (int)GamepadButton.North));

            mKeys.Add(new KeyInfo(EControllerType.Controller, false, ECustomizableKey.Customizable, "Up", (int)GamepadButton.DpadUp));
            mKeys.Add(new KeyInfo(EControllerType.Controller, false, ECustomizableKey.Customizable, "Down", (int)GamepadButton.DpadDown));
            mKeys.Add(new KeyInfo(EControllerType.Controller, false, ECustomizableKey.Customizable, "Left", (int)GamepadButton.DpadLeft));
            mKeys.Add(new KeyInfo(EControllerType.Controller, false, ECustomizableKey.Customizable, "Right", (int)GamepadButton.DpadRight));

            mKeys.Add(new KeyInfo(EControllerType.Controller, false, ECustomizableKey.Customizable, "LStick", (int)GamepadButton.LeftStick));
            mKeys.Add(new KeyInfo(EControllerType.Controller, false, ECustomizableKey.Customizable, "RStick", (int)GamepadButton.RightStick));


            mKeys.Add(new KeyInfo(EControllerType.Controller, false, ECustomizableKey.SystemStart, "Start", (int)GamepadButton.Start));
            mKeys.Add(new KeyInfo(EControllerType.Controller, false, ECustomizableKey.SystemBack, "Back", (int)GamepadButton.Select));

            mKeys.Add(new KeyInfo(EControllerType.Controller, false, ECustomizableKey.Customizable, "LT", (int)GamepadButton.LeftTrigger));
            mKeys.Add(new KeyInfo(EControllerType.Controller, false, ECustomizableKey.Customizable, "RT", (int)GamepadButton.RightTrigger));
            mKeys.Add(new KeyInfo(EControllerType.Controller, false, ECustomizableKey.Customizable, "LB", (int)GamepadButton.LeftShoulder));
            mKeys.Add(new KeyInfo(EControllerType.Controller, false, ECustomizableKey.Customizable, "RB", (int)GamepadButton.RightShoulder));


            mKeys.Add(new KeyInfo(EControllerType.Controller, true, ECustomizableKey.Fallback, "Lpad X", (int)EGamepadAxis.LStick_Horizontal));
            mKeys.Add(new KeyInfo(EControllerType.Controller, true, ECustomizableKey.Fallback, "Lpad Y", (int)EGamepadAxis.LStick_Verticle));
            mKeys.Add(new KeyInfo(EControllerType.Controller, true, ECustomizableKey.Fallback, "Rpad X", (int)EGamepadAxis.RStick_Horizontal));
            mKeys.Add(new KeyInfo(EControllerType.Controller, true, ECustomizableKey.Fallback, "Rpad Y", (int)EGamepadAxis.RStick_Verticle));

            mGamepad = Gamepad.current;// InputSystem.GetDevice<Gamepad>();
        }

        public override void Release(GameInput ginput)
        {
            base.Release(ginput);

        }

        public override IInputAction GetAction(string keyName)
        {
            var size = mKeys == null ? 0 : mKeys.Count;
            for (int i = 0; i < size; i++)
            {
                var key = mKeys[i];
                if (key.keyName.EqualsIgnoreCase(keyName))
                {
                    if (key.isAxis)
                        return new Axis(this, key);
                    else
                        return new Button(this, key);

                }
            }
            return null;
        }

        public override KeyInfo[] GetKeysInfo()
        {
            return mKeys == null ? new KeyInfo[0] : mKeys.ToArray();
        }

        public override bool IsKindOf(EControllerType type)
        {
            return type == EControllerType.Controller;
        }

        protected override bool TestConnection()
        {
            if (mGamepad == null)
                mGamepad = Gamepad.current;// InputSystem.GetDevice<Gamepad>();
            return mGamepad != null && mGamepad.added;
        }

        abstract class Action : IInputAction
        {
            protected NewInputXboxController mCtrl;
            protected KeyInfo mKey;
            public Action(NewInputXboxController ctrl, KeyInfo key)
            {
                mCtrl = ctrl;
                mKey = key;
            }

            public InputController Controller => mCtrl;

            public EControllerType ControllerType => mKey.type;

            public abstract float Value { get; }

            public abstract bool HasButton { get; }

            public KeyInfo GetKeyInfo()
            {
                return mKey;
            }
        }

        class Button : Action
        {
            Gamepad mPad;
            ButtonControl mBtn;

            public Button(NewInputXboxController ctrl, KeyInfo key) : base(ctrl, key)
            {

            }

            public override float Value => HasButton ? 1 : 0;

            public override bool HasButton
            {
                get
                {
                    if (mPad != mCtrl.mGamepad)
                    {
                        mPad = mCtrl.mGamepad;
                        mBtn = mPad == null ? null : mPad[(GamepadButton)mKey.keyCode];
                    }
                    return mBtn != null && mPad.added && mBtn.isPressed;
                }
            }
        }

        enum EGamepadAxis
        {
            LStick_Horizontal,
            LStick_Verticle,
            RStick_Horizontal,
            RStick_Verticle,
        }

        class Axis : Action
        {
            Gamepad mPad;
            StickControl mStick;
            bool mVerticle;
            bool mLeftStick;

            public Axis(NewInputXboxController ctrl, KeyInfo key) : base(ctrl, key)
            {
                mVerticle = key.keyCode == (int)EGamepadAxis.LStick_Verticle || key.keyCode == (int)EGamepadAxis.RStick_Verticle;
                mLeftStick = key.keyCode == (int)EGamepadAxis.LStick_Verticle || key.keyCode == (int)EGamepadAxis.LStick_Horizontal;
            }

            public override float Value
            {
                get
                {
                    if (mPad != mCtrl.mGamepad)
                    {
                        mPad = mCtrl.mGamepad;
                        if (mPad == null)
                            mStick = null;
                        else
                            mStick = mLeftStick ? mPad.leftStick : mPad.rightStick;
                    }
                    var v = mStick == null || !mPad.added ? default : mStick.value;
                    return mVerticle ? v.y : v.x;
                }
            }

            public override bool HasButton => !Mathf.Approximately(Value, 0);
        }
    }
}

#endif